home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 April: Mac OS SDK / Dev.CD Apr 99 SDK1.toast / Development Kits / ColorSync 2.5.1 SDK / Sample Code / CSDemo 2.5 / ShellSources / qdPrintUtils.c < prev    next >
Encoding:
Text File  |  1998-09-09  |  16.6 KB  |  552 lines  |  [TEXT/CWIE]

  1. // Simple framework for Macintosh sample code
  2. //
  3. // David Hayward and Nick Thompson 
  4. // Developer Technical Support
  5. // AppleLink: DEVSUPPORT
  6. //
  7. // Copyrite 1995, Apple Computer,Inc
  8. //
  9. // This file contains the classic quickdraw printing sample code
  10. // 
  11. // 10/4/94    nick    first cut
  12.  
  13.  
  14. #include <Resources.h>
  15. #include <Errors.h>
  16. #include <TextUtils.h>
  17.  
  18. #include "qdPrintUtils.h"
  19. #include "cursorUtils.h"
  20.  
  21.  
  22. /**\
  23. |**| ==============================================================================
  24. |**| PUBLIC GLOBALS
  25. |**| ==============================================================================
  26. \**/
  27. Boolean        gPrGeneral_available = false ;
  28. long        gPrOpenCount = 0 ;
  29.  
  30.  
  31. /**\
  32. |**| ==============================================================================
  33. |**| PRIVATE FUNCTION PROTOTYPES
  34. |**| ==============================================================================
  35. \**/
  36. pascal void    IdleProc            ( void ) ;
  37. OSErr        CommandPeriod        ( void ) ;
  38. void        MyPrOpen            ( void ) ;
  39. void        MyPrClose            ( void ) ;
  40. void        UpdateStatusDialog    ( QDPrintLoopParamsPtr params ) ;
  41.  
  42.  
  43. /**\
  44. |**| ==============================================================================
  45. |**| PUBLIC FUNCTIONS
  46. |**| ==============================================================================
  47. \**/
  48.  
  49.  
  50. /*------------------------------------------------------------------------------*\
  51.     QDPrinting_available
  52.  *------------------------------------------------------------------------------*
  53.         This function returns noErr if the QuickDraw printing is 
  54.         available to the application and returns an appropriate err otherwise.
  55.         It also checks to see if PrGeneral is available and returns an
  56.         appropriate err otherwise.
  57. \*------------------------------------------------------------------------------*/
  58. OSErr QDPrinting_available ( void ) 
  59. {
  60.     OSErr         err ;
  61.     TGetRslBlk    getResRec ;
  62.  
  63.     MyPrOpen() ;
  64.     
  65.     err = PrError() ;
  66.     if ( err == fnfErr )    // Here, "file not found" really means "no printer chosen."
  67.         err = noPrinterChosenErr ;
  68.     if ( err ) return err ;
  69.     
  70.     getResRec.iOpCode = getRslDataOp;
  71.     PrGeneral((Ptr) &getResRec) ;
  72.     err = PrError() ;
  73.  
  74.     MyPrClose() ;
  75.  
  76.     return err ;
  77. }
  78.  
  79.  
  80. /*------------------------------------------------------------------------------*\
  81.     GetDefaultTHPrint
  82.  *------------------------------------------------------------------------------*
  83.         This routine returns a default print handle for the current printer driver.
  84.         The printer driver is expected to be closed upon entry, and is therefore
  85.         opened and closed in this routine.
  86. \*------------------------------------------------------------------------------*/
  87. OSErr GetDefaultTHPrint (THPrint *hPrint)
  88. {
  89.     OSErr         err ;
  90.     
  91.     err = QDPrinting_available() ;
  92.     if ( err ) return err ;
  93.         
  94.     // Create a handle, open the printer driver, set the
  95.     // default values for the handle, and close the driver.
  96.     // Be on the lookout for errors.
  97.  
  98.     *hPrint = (THPrint) NewHandle(sizeof(TPrint)) ;
  99.     if (*hPrint == nil)
  100.         return MemError() ;
  101.         
  102.     MyPrOpen() ;
  103.     PrintDefault(*hPrint) ;
  104.     err = PrError() ;
  105.     MyPrClose() ;
  106.  
  107.     if ( err )
  108.     {
  109.         DisposeHandle( (Handle)*hPrint ) ;
  110.         *hPrint = nil ;
  111.     }
  112.     return err ;
  113. }
  114.  
  115.  
  116. /*------------------------------------------------------------------------------*\
  117.     LoadResourceTHPrint
  118.  *------------------------------------------------------------------------------*
  119.         This routine loads a print handle resource with the resType r_printHdlType
  120.         If there is no print record resource in the indicated resource file,
  121.         the function returns resNotFound.
  122.         Upon entry, hPrint is expected to be a valid print handle or nil.
  123.         The printer driver is expected to be closed upon entry,and is therefore
  124.         opened and closed in this routine.
  125. \*------------------------------------------------------------------------------*/
  126. OSErr LoadResourceTHPrint ( THPrint *hPrint, FSSpec *spec )
  127. {
  128.     short        savedRefNum;
  129.     short        resRefNum;
  130.     Handle        resHandle;
  131.     OSErr        err = noErr ;
  132.     Boolean        changed = false ;
  133.  
  134.     resRefNum = FSpOpenResFile( spec, fsRdPerm) ;
  135.     if (resRefNum == -1)
  136.         return fnfErr ;
  137.         
  138.     savedRefNum = CurResFile() ;            // Save the current resource file refNum
  139.     UseResFile(resRefNum) ;                    // set the current res file
  140.     
  141.     // Get our resource, if there is one
  142.     resHandle = Get1IndResource(r_printHdlType,1) ;
  143.     if ( resHandle==nil )
  144.         err = ResError() ;
  145.     else
  146.     {
  147.         if (*hPrint)                            // If we previously had a print handle
  148.             DisposeHandle( (Handle)*hPrint ) ;    // dispose of it before passing this new one back
  149.         *hPrint = (THPrint) resHandle;
  150.         HandToHand( (Handle*)hPrint ) ;
  151.         MyPrOpen() ;
  152.         changed = PrValidate( *hPrint ) ;        // check we have a "good" print record
  153.         MyPrClose() ;
  154.     }
  155.     
  156.     if ( resHandle) ReleaseResource( resHandle ) ;
  157.     CloseResFile( resRefNum ) ;
  158.     UseResFile( savedRefNum ) ;                // switch back to the original resource file.
  159.     return err ;
  160. }
  161.  
  162.  
  163. /*------------------------------------------------------------------------------*\
  164.     SaveResourceTHPrint
  165.  *------------------------------------------------------------------------------*
  166.         This routine saves the passed print handle in resource fork of the 
  167.         indicated file. If there are already a print record resources, they are
  168.         deleted and replaced.
  169. \*------------------------------------------------------------------------------*/
  170. OSErr SaveResourceTHPrint ( THPrint hPrint, FSSpec *spec )
  171. {
  172.     short        savedRefNum, uniqID;
  173.     OSErr        err = noErr ;
  174.     Handle        oldHdl;
  175.     short        resRefNum;
  176.     
  177.     resRefNum = FSpOpenResFile( spec, fsWrPerm) ;
  178.     if (resRefNum == -1)
  179.         return fnfErr ;
  180.         
  181.     // Make a copy of the hPrint handle.
  182.     oldHdl = (Handle)hPrint ;                    // this is needed because CloseResFile
  183.     err = HandToHand( &oldHdl );                // will dispose of the handle later
  184.  
  185.     if (!err)
  186.     {
  187.         savedRefNum = CurResFile() ;            // Save the current resource file refNum
  188.         UseResFile(resRefNum) ;                    // set the current res file
  189.         
  190.         // remove any existing resources
  191.         while ( (oldHdl=Get1IndResource(r_printHdlType,1)) != nil )
  192.         {
  193.             RemoveResource(oldHdl) ;            // remove the resource from the file
  194.             DisposeHandle(oldHdl) ;                // free the handle that is left behind
  195.         }
  196.     
  197.         // Save the new resource with a unique ID.
  198.         uniqID = Unique1ID( r_printHdlType ) ;
  199.         AddResource( oldHdl, r_printHdlType, uniqID, "\p") ;
  200.         err = ResError() ;
  201.         
  202.         UseResFile(savedRefNum) ;                // switch back to the original resource file.
  203.     }
  204.     
  205.     CloseResFile( resRefNum ) ;
  206.     FlushVol( nil , spec->vRefNum ) ;
  207.     return err ;
  208. }
  209.  
  210.  
  211. /*------------------------------------------------------------------------------*\
  212.     QDGetPageSize
  213.  *------------------------------------------------------------------------------*
  214. \*------------------------------------------------------------------------------*/
  215. OSErr QDGetPageSize ( THPrint hPrint, Rect *pageRect )
  216. {
  217.     *pageRect = (**hPrint).prInfo.rPage ;
  218.     return noErr ; 
  219. }
  220.  
  221.  
  222.  
  223. /*------------------------------------------------------------------------------*\
  224.     QDStyleDlog
  225.  *------------------------------------------------------------------------------*
  226.         This routine displays the standard Page Setup dialog
  227. \*------------------------------------------------------------------------------*/
  228. OSErr QDStyleDlog( THPrint hPrint )
  229. {
  230.     OSErr    err = noErr ;
  231.     Boolean    changed = false ;
  232.     
  233.     MyPrOpen() ;
  234.     err = PrError() ;
  235.     
  236.     if( !err )
  237.     {
  238.         changed = PrStlDialog(hPrint) ;
  239.         err = PrError() ;
  240.         if (!err && !changed) err = iPrAbort ;
  241.     }
  242.  
  243.     MyPrClose() ;
  244.     return err ;
  245. }
  246.  
  247.  
  248. /*------------------------------------------------------------------------------*\
  249.     QDJobDlog
  250.  *------------------------------------------------------------------------------*
  251.         This routine displays the standard Print dialog
  252. \*------------------------------------------------------------------------------*/
  253. OSErr QDJobDlog (THPrint hPrint)
  254. {
  255.     OSErr    err = noErr ;
  256.     Boolean    changed = false ;
  257.     
  258.     MyPrOpen() ;
  259.     err = PrError() ;
  260.     
  261.     if ( !err )
  262.     {
  263.         changed = PrJobDialog(hPrint) ;
  264.         err = PrError() ;
  265.         if ( !err && !changed ) err = iPrAbort;
  266.     }
  267.  
  268.     MyPrClose() ;
  269.     return err ;
  270. }
  271.  
  272.  
  273. /*------------------------------------------------------------------------------*\
  274.     QDPrintLoopBegin
  275.  *------------------------------------------------------------------------------*
  276. \*------------------------------------------------------------------------------*/
  277. OSErr QDPrintLoopBegin ( QDPrintLoopParamsPtr params ) 
  278. {
  279.     OSErr                err ;
  280.     long                jobFirst, jobLast ;
  281.     Str255                title ;
  282.     PrIdleUPP            idleUPP=nil ;
  283.     GrafPtr                savedPort ;
  284.     
  285.     GetPort( &savedPort ) ;
  286.  
  287.     MyPrOpen() ;
  288.     err = PrError() ;
  289.     if ( err ) goto PROpenFailed ;
  290.     
  291.     // we don't assign this directly because NewPrIdleProc may move memory,
  292.     // so assign to an intermediate variable idleUPP
  293.     idleUPP = NewPrIdleProc(IdleProc) ;
  294.     (**(params->hPrint)).prJob.pIdleProc = idleUPP ;
  295.  
  296.     //    Determine which pages the user selected to print.
  297.     //    If the user specifies a range that is greater than the actual number
  298.     //    of pages, then only print those pages that are in the document. 
  299.     jobFirst = (**(params->hPrint)).prJob.iFstPage ;
  300.     jobLast  = (**(params->hPrint)).prJob.iLstPage ;
  301.     if (jobFirst > params->firstPage) params->firstPage = jobFirst;
  302.     if (jobLast  < params->lastPage ) params->lastPage = jobLast;
  303.     
  304.     // dialog stuff
  305.     params->currentPage = params->firstPage - 1 ;    // make curPage out of range
  306.     params->statusDialog = GetNewDialog( 1005, nil, (WindowRef)-1 );
  307.     GetWTitle( params->window, title ) ;
  308.     UpdateStatusDialog( params ) ;
  309.     ShowWindow( (WindowRef)(params->statusDialog) ) ;
  310.  
  311.     //    begin printing if there are no errors.
  312.     params->printingPort = (GrafPtr)PrOpenDoc( params->hPrint, nil, nil ) ;
  313.     err = PrError() ;
  314.     if ( err ) goto PROpenDocFailed;
  315.     
  316.     return noErr ;
  317.     
  318.     
  319. PROpenDocFailed:
  320.     MyPrClose() ;
  321.     
  322. PROpenFailed:
  323.     if (idleUPP) DisposeRoutineDescriptor( (UniversalProcPtr)idleUPP ) ;
  324.     DisposeDialog( params->statusDialog ) ;
  325.     SetPort( savedPort ) ;
  326.     return err ;
  327. }
  328.  
  329.  
  330. /*------------------------------------------------------------------------------*\
  331.     QDPrintLoopPageBefore
  332.  *------------------------------------------------------------------------------*
  333. \*------------------------------------------------------------------------------*/
  334. OSErr QDPrintLoopPageBefore ( QDPrintLoopParamsPtr params ) 
  335. {
  336.     OSErr            err ;
  337.     
  338.     // update dialog
  339.     UpdateStatusDialog( params ) ;
  340.  
  341.     SetPort( params->printingPort ) ;
  342.     PrOpenPage( (TPPrPort)(params->printingPort), nil ) ;
  343.     err = PrError() ;
  344.     return err ;
  345. }
  346.  
  347.  
  348. /*------------------------------------------------------------------------------*\
  349.     QDPrintLoopPageAfter
  350.  *------------------------------------------------------------------------------*
  351. \*------------------------------------------------------------------------------*/
  352. OSErr QDPrintLoopPageAfter ( QDPrintLoopParamsPtr params ) 
  353. {
  354.     OSErr            err ;
  355.  
  356.     PrClosePage( (TPPrPort)(params->printingPort) ) ;
  357.     err = PrError() ;
  358.     return err ;
  359. }
  360.  
  361.  
  362. /*------------------------------------------------------------------------------*\
  363.     QDPrintLoopEnd
  364.  *------------------------------------------------------------------------------*
  365. \*------------------------------------------------------------------------------*/
  366. OSErr QDPrintLoopEnd ( QDPrintLoopParamsPtr params ) 
  367. {
  368.     OSErr            err ;
  369.     PrIdleUPP        idleUPP ; 
  370.     TPrStatus         theStatus ;
  371.  
  372.     // update dialog
  373.     UpdateStatusDialog( params ) ;
  374.  
  375.     PrCloseDoc( (TPPrPort)(params->printingPort) ) ;
  376.     err = PrError() ;
  377.     
  378.     // if we're printing to our good friend the ImageWriter, or similar, despool
  379.     if( ( !err ) && ((**(params->hPrint)).prJob.bJDocLoop == bSpoolLoop))
  380.         PrPicFile( params->hPrint, nil, nil, nil, &theStatus ) ; 
  381.         
  382.     PrClose() ;
  383.     
  384.     // Dispose IdleProc UPP
  385.     idleUPP = (**(params->hPrint)).prJob.pIdleProc ;
  386.     DisposeRoutineDescriptor( (UniversalProcPtr)idleUPP ) ;
  387.  
  388.     // Dispose Dialog
  389.     DisposeDialog( params->statusDialog ) ;
  390.     
  391.     return err ;
  392. }
  393.  
  394.  
  395. /*------------------------------------------------------------------------------*\
  396.     DoQDPrintLoop
  397.  *------------------------------------------------------------------------------*
  398.         This is a basic classic QD print loop
  399. \*------------------------------------------------------------------------------*/
  400. /*OSErr DoQDPrintLoop ( THPrint hPrint, long firstPage, long lastPage, winHandle win ) 
  401. {
  402.     OSErr                    err ;
  403.     GrafPtr                    savedPort ;
  404.     QDPrintLoopParamsRec    params ;
  405.     
  406.     GetPort( &savedPort ) ;
  407.     
  408.     params.hPrint = hPrint ;
  409.     params.window = GetWinWindow(win) ;
  410.     params.firstPage = firstPage ;
  411.     params.lastPage = lastPage ;
  412.         
  413.     err = QDPrintLoopBegin( ¶ms ) ;
  414.     if (err) return err ;
  415.     
  416.     for (    params.currentPage = params.firstPage;
  417.             params.currentPage <= params.lastPage && !err ;
  418.             params.currentPage ++ )
  419.     {
  420.         if (!err) err = QDPrintLoopPageBefore( ¶ms ) ;
  421.         if (!err) err = CallWinPagePrintProc( win, params.printingPort, params.currentPage ) ;
  422.         if (!err) err = QDPrintLoopPageAfter( ¶ms ) ;
  423.     }
  424.     
  425.     err = QDPrintLoopEnd( ¶ms ) ;
  426.     SetPort( savedPort ) ;
  427.     return err ;
  428. }*/
  429.  
  430.  
  431. /**\
  432. |**| ==============================================================================
  433. |**| PRIVATE FUNCTIONS
  434. |**| ==============================================================================
  435. \**/
  436.  
  437.  
  438. /*------------------------------------------------------------------------------*\
  439.     MyPrOpen
  440.  *------------------------------------------------------------------------------*
  441.         This routine allows nested calls to PrOpen/PrClose be keeping track of
  442.         the number of calls that have been made in the global gPrOpenCount.
  443.         It does not return any error so you still need to call PrError ofter this.
  444. \*------------------------------------------------------------------------------*/
  445. static void MyPrOpen ( void )
  446. {
  447.     if ( gPrOpenCount==0 )            // if we haven't called it yet
  448.         PrOpen() ;                    // open it
  449.     gPrOpenCount++ ;                // increment the count
  450. }
  451.  
  452.  
  453. /*------------------------------------------------------------------------------*\
  454.     MyPrClose
  455.  *------------------------------------------------------------------------------*
  456.         This routine allows nested calls to PrOpen/PrClose be keeping track of
  457.         the number of calls that have been made in the global gPrOpenCount.
  458. \*------------------------------------------------------------------------------*/
  459. static void MyPrClose ( void )
  460. {
  461.     gPrOpenCount-- ;                // increment the count
  462.     if ( gPrOpenCount==0 )            // if the count is down to zero
  463.         PrClose() ;                    // close it
  464. }
  465.  
  466.  
  467. /*------------------------------------------------------------------------------*\
  468.     IdleProc
  469.  *------------------------------------------------------------------------------*
  470.         This routine is a PrIdleProcPtr that spins our cursor and looks for
  471.         command-period presses during printing.
  472. \*------------------------------------------------------------------------------*/
  473. static pascal void IdleProc ( void )
  474. {
  475.     OSErr        err ;
  476.  
  477.     BumpCursor() ;
  478.     err = CommandPeriod() ;
  479.     if ( err ) PrSetError( err ) ;
  480. }
  481.  
  482.  
  483. /*------------------------------------------------------------------------------*\
  484.     CommandPeriod
  485.  *------------------------------------------------------------------------------*
  486.         This routine checks to see if the user has pressed command-period.
  487.         The Printing Manager does this for us, but a routine like this is helpful
  488.         to allow users to cancel in the middle of a rendering routine, rather
  489.         than only Printing Manager operations.
  490.         If there's a command-period in the event queue, the routine returns
  491.         iPrAbort just like the Printing Manager.  Otherwise, it returns noErr
  492. \*------------------------------------------------------------------------------*/
  493. static OSErr CommandPeriod ( void )
  494. {
  495.     Boolean            userCancel = false ;
  496.     short            itemHit ;
  497.     short            eventMask = keyDownMask|autoKeyMask|mDownMask ;
  498.     EventRecord        evtRec ;
  499.     WindowRef        window ;
  500.     
  501.     if ( WaitNextEvent( eventMask, &evtRec, 0, nil) )
  502.     {
  503.         switch (evtRec.what)
  504.         {
  505.             case autoKey:
  506.             case keyDown:
  507.                 userCancel = (evtRec.modifiers & cmdKey) &&
  508.                           ((evtRec.message & charCodeMask) == '.') ;
  509.                 break ;
  510.             
  511.             case mouseDown:
  512.                 if ( IsDialogEvent(&evtRec))
  513.                     if ( FindWindow(evtRec.where,&window) == inContent )
  514.                         // should confirm it is our dialog here
  515.                             if ( DialogSelect(&evtRec,(DialogPtr*)&window,&itemHit) )
  516.                                 userCancel = (itemHit == kStdCancelItemIndex ) ;
  517.                 break ;
  518.         }
  519.     }
  520.     return ( (userCancel) ? (iPrAbort) : (noErr) ) ;
  521. }
  522.  
  523.  
  524. /*------------------------------------------------------------------------------*\
  525.     UpdateStatusDialog
  526.  *------------------------------------------------------------------------------*
  527.         This routine 
  528. \*------------------------------------------------------------------------------*/
  529. static void UpdateStatusDialog ( QDPrintLoopParamsPtr params )
  530. {
  531.     long        cPage, fPage, lPage ;
  532.     Str255        strA, strC, strD ;
  533.     
  534.     cPage = params->currentPage ;
  535.     fPage = params->firstPage ;
  536.     lPage = params->lastPage ;
  537.     
  538.     if ( ( cPage>=fPage ) && ( cPage<=lPage ) )
  539.     {
  540.         GetWTitle( params->window, strA ) ;
  541.         NumToString( cPage - fPage +1, strC);
  542.         NumToString( lPage - fPage +1, strD);
  543.         ParamText( strA, "\pprinter", strC, strD ) ;
  544.         ShowDialogItem( params->statusDialog, 4 ) ;
  545.     }
  546.     else
  547.         HideDialogItem( params->statusDialog, 4 ) ;
  548.         
  549.     DrawDialog( params->statusDialog ) ;
  550. }
  551.  
  552.